package main

import (
	"fmt"
	"time"
)

// select 多路复用
// 什么是多路复用：同时监听多个分支，哪个分支有读或写的事件触发，我就ok，那么就打破阻塞并执行
// 0、··· 用于传递父子context之间的channel事件 ···
// 1. 当程序汇总有多个channel协同工作，cha1 cha2在某一个时刻，ch1或者ch2触发了，程序要做响应处理
// 2. 使用select来监听多个通道，当管道被触发时(写入数据、读取数据、关闭通道)
// 3. select语法与switch case很像，但是所有分支条件都必须是io
// 4. 使用select语句能提高代码的可读性
// 	  4.1 可处理一个或多个channel的发送/接收操作
// 	  4.2 如果多个case同时满足，select会随机选择一个
// 	  4.3 对于没有case的select{}会一直等待，可用于阻塞main函数

func main() {
	var ch1 = make(chan int, 100)
	var ch2 = make(chan int, 200)

	// 启动一个go程序监听ch1 ch2
	go func() {
		for {
			fmt.Println("---监听中---")
			select {
			case data1 := <-ch1:
				fmt.Println("从ch1读取到的数据, data1: ", data1)
			case data2 := <-ch2:
				fmt.Println("从ch2读取到的数据, data2: ", data2)
			default: // 当没有数据时候，可以加个default终止监听
				fmt.Println("select default called")
				time.Sleep(time.Second)
			}
		}
	}()

	// 启动一个go程序 写入数据
	go func() {
		for i := 0; i < 10; i++ {
			ch1 <- i
			time.Sleep(time.Second)
		}
	}()

	// 启动一个go程序 写入数据
	go func() {
		for i := 0; i < 10; i++ {
			ch2 <- i
			time.Sleep(time.Second)
		}
	}()

	for {
		fmt.Println("---over!---")
		time.Sleep(5 * time.Second)
	}
}
